<html><head><title>unique_ptr emulation Implementation</title>


<style>
p {text-align:justify}
li {text-align:justify}
blockquote.note
{
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
}
ins {background-color:#FFFFA0}
del {background-color:#FFFFA0}
</style></head><body>

<address align="right">
<a href="mailto:hinnant@twcny.rr.com">Howard E. Hinnant</a><br>
2006-05-16
</address>
<hr>

<h1 align="center"><tt>unique_ptr</tt> emulation Implementation</h1>

<p>
See C++0X reference implementation <a href="http://home.twcny.rr.com/hinnant/cpp_extensions/unique_ptr.html">here</a>.
</p>

<p>
Known bugs:
</p>

<ul>
<li>
<p>
This implementation will mistakenly move from <tt>const</tt> lvalues.
</p>
<blockquote><pre>const unique_ptr&lt;int&gt; cp;
unique_ptr&lt;int&gt; p(cp);  // should not compile
</pre></blockquote>
</li>

<li>
<p>
This implementation will not implicitly move from local auto variables on
the return statement.  An explicit move must be used.
</p>
<blockquote><pre>unique_ptr&lt;int&gt;
foo()
{
    unique_ptr&lt;int&gt; result;
    return move(result);  // move should not be required
}
</pre></blockquote>
</li>
</ul>

<p>
Source:
</p>

<blockquote><pre>// I, Howard Hinnant, hereby place this code in the public domain.

#include &lt;boost/compressed_pair.hpp&gt;
#include &lt;boost/static_assert.hpp&gt;
#include &lt;boost/mpl/if.hpp&gt;
#include &lt;boost/type_traits.hpp&gt;
#include &lt;boost/utility/enable_if.hpp&gt;
#include &lt;cstddef&gt;

namespace detail
{

struct two {char _[2];};

namespace pointer_type_imp
{

template &lt;class U&gt; static two  test(...);
template &lt;class U&gt; static char test(typename U::pointer* = 0);

}

template &lt;class T&gt;
struct has_pointer_type
{
    static const bool value = sizeof(pointer_type_imp::test&lt;T&gt;(0)) == 1;
};

namespace pointer_type_imp
{

template &lt;class T, class D, bool = has_pointer_type&lt;D&gt;::value&gt;
struct pointer_type
{
    typedef typename D::pointer type;
};

template &lt;class T, class D&gt;
struct pointer_type&lt;T, D, false&gt;
{
    typedef T* type;
};

}

template &lt;class T, class D&gt;
struct pointer_type
{
    typedef typename pointer_type_imp::pointer_type&lt;T,
        typename boost::remove_reference&lt;D&gt;::type&gt;::type type;
};

}

template &lt;class T&gt;
struct default_delete
{
    default_delete() {}
    template &lt;class U&gt; default_delete(const default_delete&lt;U&gt;&amp;) {}
    void operator() (T* ptr) const
    {
        BOOST_STATIC_ASSERT(sizeof(T) &gt; 0);
        delete ptr;
    }
};

template &lt;class T&gt;
struct default_delete&lt;T[]&gt;
{
    void operator() (T* ptr) const
    {
        BOOST_STATIC_ASSERT(sizeof(T) &gt; 0);
        delete [] ptr;
    }
};

template &lt;class T, std::size_t N&gt;
struct default_delete&lt;T[N]&gt;
{
    void operator() (T* ptr, std::size_t) const
    {
        BOOST_STATIC_ASSERT(sizeof(T) &gt; 0);
        delete [] ptr;
    }
};

template &lt;class T, class D&gt; class unique_ptr;

namespace detail
{

template &lt;class T&gt; struct unique_ptr_error;

template &lt;class T, class D&gt;
struct unique_ptr_error&lt;const unique_ptr&lt;T, D&gt; &gt;
{
    typedef unique_ptr&lt;T, D&gt; type;
};

}  // detail

template &lt;class T, class D = default_delete&lt;T&gt; &gt;
class unique_ptr
{
    struct nat {int for_bool_;};
    typedef typename boost::add_reference&lt;D&gt;::type deleter_reference;
    typedef typename boost::add_reference&lt;const D&gt;::type deleter_const_reference;
public:
    typedef T element_type;
    typedef D deleter_type;
    typedef typename detail::pointer_type&lt;T, D&gt;::type pointer;

    // constructors
    unique_ptr() : ptr_(pointer())
    {
        BOOST_STATIC_ASSERT(!boost::is_pointer&lt;D&gt;::value);
    }
    explicit unique_ptr(pointer p) : ptr_(p)
    {
        BOOST_STATIC_ASSERT(!boost::is_pointer&lt;D&gt;::value);
    }
    unique_ptr(pointer p, typename boost::mpl::if_&lt;
                         boost::is_reference&lt;D&gt;,
                         D,
                         typename boost::add_reference&lt;const D&gt;::type&gt;::type d)
        : ptr_(p, d) {}
    unique_ptr(const unique_ptr&amp; u)
        : ptr_(const_cast&lt;unique_ptr&amp;&gt;(u).release(), u.get_deleter()) {}
    template &lt;class U, class E&gt;
        unique_ptr(const unique_ptr&lt;U, E&gt;&amp; u,
            typename boost::enable_if_c&lt;
                boost::is_convertible&lt;typename unique_ptr&lt;U, E&gt;::pointer, pointer&gt;::value &amp;&amp;
                boost::is_convertible&lt;E, D&gt;::value &amp;&amp;
                (
                    !boost::is_reference&lt;D&gt;::value ||
                     boost::is_same&lt;D, E&gt;::value
                )
                ,
                nat
                &gt;::type = nat())
            : ptr_(const_cast&lt;unique_ptr&lt;U,E&gt;&amp;&gt;(u).release(), u.get_deleter()) {}

    // destructor
    ~unique_ptr() {reset();}

    // assignment
    unique_ptr&amp; operator=(const unique_ptr&amp; cu)
   {
        unique_ptr&amp; u = const_cast&lt;unique_ptr&amp;&gt;(cu);
        reset(u.release());
        ptr_.second() = u.get_deleter();
        return *this;
    }
    template &lt;class U, class E&gt;
    unique_ptr&amp; operator=(const unique_ptr&lt;U, E&gt;&amp; cu)
    {
        unique_ptr&lt;U, E&gt;&amp; u = const_cast&lt;unique_ptr&lt;U, E&gt;&amp;&gt;(cu);
        reset(u.release());
        ptr_.second() = u.get_deleter();
        return *this;
    }
    unique_ptr&amp; operator=(int nat::*)
    {
        reset();
        return *this;
    }

    // observers
    typename boost::add_reference&lt;T&gt;::type operator*()  const {return *ptr_.first();}
    pointer operator-&gt;() const {return ptr_.first();}
    pointer get()        const {return ptr_.first();}
    deleter_reference       get_deleter()       {return ptr_.second();}
    deleter_const_reference get_deleter() const {return ptr_.second();}
    operator int nat::*() const {return ptr_.first() ? &amp;nat::for_bool_ : 0;}

    // modifiers
    pointer release()
    {
        pointer tmp = ptr_.first();
        ptr_.first() = pointer();
        return tmp;
    }
    void reset(pointer p = pointer())
    {
        if (ptr_.first() != p)
        {
            if (ptr_.first())
                ptr_.second()(ptr_.first());
            ptr_.first() = p;
        }
    }
    void swap(unique_ptr&amp; u) {ptr_.swap(u.ptr_);}
private:
    boost::compressed_pair&lt;pointer, D&gt; ptr_;

    unique_ptr(unique_ptr&amp;);
    template &lt;class U, class E&gt; unique_ptr(unique_ptr&lt;U, E&gt;&amp;);
    template &lt;class U&gt; unique_ptr(U&amp;, typename detail::unique_ptr_error&lt;U&gt;::type = 0);

    
    unique_ptr&amp; operator=(unique_ptr&amp;);
    template &lt;class U, class E&gt; unique_ptr&amp; operator=(unique_ptr&lt;U, E&gt;&amp;);
    template &lt;class U&gt; typename detail::unique_ptr_error&lt;U&gt;::type operator=(U&amp;);
};

template &lt;class T, class D&gt;
class unique_ptr&lt;T[], D&gt;
{
    struct nat {int for_bool_;};
    typedef typename boost::add_reference&lt;D&gt;::type deleter_reference;
    typedef typename boost::add_reference&lt;const D&gt;::type deleter_const_reference;
public:
    typedef T element_type;
    typedef D deleter_type;
    typedef typename detail::pointer_type&lt;T, D&gt;::type pointer;

    // constructors
    unique_ptr() : ptr_(pointer())
    {
        BOOST_STATIC_ASSERT(!boost::is_pointer&lt;D&gt;::value);
    }
    explicit unique_ptr(pointer p) : ptr_(p)
    {
        BOOST_STATIC_ASSERT(!boost::is_pointer&lt;D&gt;::value);
    }
    unique_ptr(pointer p, typename boost::mpl::if_&lt;
                          boost::is_reference&lt;D&gt;,
                          D,
                          typename boost::add_reference&lt;const D&gt;::type&gt;::type d)
        : ptr_(p, d) {}
    unique_ptr(const unique_ptr&amp; u)
        : ptr_(const_cast&lt;unique_ptr&amp;&gt;(u).release(), u.get_deleter()) {}

    // destructor
    ~unique_ptr() {reset();}

    // assignment
    unique_ptr&amp; operator=(const unique_ptr&amp; cu)
    {
        unique_ptr&amp; u = const_cast&lt;unique_ptr&amp;&gt;(cu);
        reset(u.release());
        ptr_.second() = u.get_deleter();
        return *this;
    }
    unique_ptr&amp; operator=(int nat::*)
    {
        reset();
        return *this;
    }

    // observers
    typename boost::add_reference&lt;T&gt;::type operator[](std::size_t i)  const {return ptr_.first()[i];}
    pointer get()        const {return ptr_.first();}
    deleter_reference       get_deleter()       {return ptr_.second();}
    deleter_const_reference get_deleter() const {return ptr_.second();}
    operator int nat::*() const {return ptr_.first() ? &amp;nat::for_bool_ : 0;}

    // modifiers
    pointer release()
    {
        pointer tmp = ptr_.first();
        ptr_.first() = pointer();
        return tmp;
    }
    void reset(pointer p = pointer())
    {
        if (ptr_.first() != p)
        {
            if (ptr_.first())
                ptr_.second()(ptr_.first());
            ptr_.first() = p;
        }
    }
    void swap(unique_ptr&amp; u) {ptr_.swap(u.ptr_);}
private:
    boost::compressed_pair&lt;pointer, D&gt; ptr_;

    template &lt;class U, class E&gt; unique_ptr(U p, E,
        typename boost::enable_if&lt;boost::is_convertible&lt;U, pointer&gt; &gt;::type* = 0);
    template &lt;class U&gt; explicit unique_ptr(U,
        typename boost::enable_if&lt;boost::is_convertible&lt;U, pointer&gt; &gt;::type* = 0);

    unique_ptr(unique_ptr&amp;);
    template &lt;class U&gt; unique_ptr(U&amp;, typename detail::unique_ptr_error&lt;U&gt;::type = 0);

    unique_ptr&amp; operator=(unique_ptr&amp;);
    template &lt;class U&gt; typename detail::unique_ptr_error&lt;U&gt;::type operator=(U&amp;);
};

template &lt;class T, class D, std::size_t N&gt;
class unique_ptr&lt;T[N], D&gt;
{
    struct nat {int for_bool_;};
    typedef typename boost::add_reference&lt;D&gt;::type deleter_reference;
    typedef typename boost::add_reference&lt;const D&gt;::type deleter_const_reference;
public:
    typedef T element_type;
    typedef D deleter_type;
    typedef typename detail::pointer_type&lt;T, D&gt;::type pointer;
    static const std::size_t size = N;

    // constructors
    unique_ptr() : ptr_(pointer())
    {
        BOOST_STATIC_ASSERT(!boost::is_pointer&lt;D&gt;::value);
    }
    explicit unique_ptr(pointer p) : ptr_(p)
    {
        BOOST_STATIC_ASSERT(!boost::is_pointer&lt;D&gt;::value);
    }
    unique_ptr(pointer p, typename boost::mpl::if_&lt;
                         boost::is_reference&lt;D&gt;,
                         D,
                         typename boost::add_reference&lt;const D&gt;::type&gt;::type d)
        : ptr_(p, d) {}
    unique_ptr(const unique_ptr&amp; u)
        : ptr_(const_cast&lt;unique_ptr&amp;&gt;(u).release(), u.get_deleter()) {}

    // destructor
    ~unique_ptr() {reset();}

    // assignment
    unique_ptr&amp; operator=(const unique_ptr&amp; cu)
    {
        unique_ptr&amp; u = const_cast&lt;unique_ptr&amp;&gt;(cu);
        reset(u.release());
        ptr_.second() = u.get_deleter();
        return *this;
    }
    unique_ptr&amp; operator=(int nat::*)
    {
        reset();
        return *this;
    }

    // observers
    typename boost::add_reference&lt;T&gt;::type operator[](std::size_t i)  const {return ptr_.first()[i];}
    pointer get()        const {return ptr_.first();}
    deleter_reference       get_deleter()       {return ptr_.second();}
    deleter_const_reference get_deleter() const {return ptr_.second();}
    operator int nat::*() const {return ptr_.first() ? &amp;nat::for_bool_ : 0;}

    // modifiers
    pointer release()
    {
        pointer tmp = ptr_.first();
        ptr_.first() = pointer();
        return tmp;
    }
    void reset(pointer p = pointer())
    {
        if (ptr_.first() != p)
        {
            if (ptr_.first())
                ptr_.second()(ptr_.first(), N);
            ptr_.first() = p;
        }
    }
    void swap(unique_ptr&amp; u) {ptr_.swap(u.ptr_);}
private:
    boost::compressed_pair&lt;pointer, D&gt; ptr_;

    template &lt;class U, class E&gt; unique_ptr(U p, E,
        typename boost::enable_if&lt;boost::is_convertible&lt;U, pointer&gt; &gt;::type* = 0);
    template &lt;class U&gt; explicit unique_ptr(U,
        typename boost::enable_if&lt;boost::is_convertible&lt;U, pointer&gt; &gt;::type* = 0);

    unique_ptr(unique_ptr&amp;);
    template &lt;class U&gt; unique_ptr(U&amp;, typename detail::unique_ptr_error&lt;U&gt;::type = 0);

    unique_ptr&amp; operator=(unique_ptr&amp;);
    template &lt;class U&gt; typename detail::unique_ptr_error&lt;U&gt;::type operator=(U&amp;);
};

template &lt;class T, class D&gt;
inline
void swap(unique_ptr&lt;T, D&gt;&amp; x, unique_ptr&lt;T, D&gt;&amp; y) {x.swap(y);}

template &lt;class T1, class D1, class T2, class D2&gt;
inline
bool
operator==(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y)
    {return x.get() == y.get();}

template &lt;class T1, class D1, class T2, class D2&gt;
inline
bool
operator!=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y)
    {return x.get() != y.get();}

template &lt;class T1, class D1, class T2, class D2&gt;
inline
bool
operator &lt;(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y)
    {return x.get() &lt; y.get();}

template &lt;class T1, class D1, class T2, class D2&gt;
inline
bool
operator&lt;=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y)
    {return x.get() &lt;= y.get();}

template &lt;class T1, class D1, class T2, class D2&gt;
inline
bool
operator &gt;(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y)
    {return x.get() &gt; y.get();}

template &lt;class T1, class D1, class T2, class D2&gt;
inline
bool
operator&gt;=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y)
    {return x.get() &gt;= y.get();}

template &lt;class T, class D&gt;
inline
unique_ptr&lt;T, D&gt;
move(unique_ptr&lt;T, D&gt;&amp; p)
{
    return unique_ptr&lt;T, D&gt;(p.release(), p.get_deleter());
}
</pre></blockquote>


</body></html>